package gameObjects
{
	import Box2D.Collision.b2AABB;
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2BodyDef;
	import Box2D.Dynamics.b2Fixture;
	import Box2D.Dynamics.b2World;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.display.Stage;
	
	/**
	 * @author Leong Shi Yun
	 */
	public class GameObject
	{
		/* private var/const */
		protected var m_b2Body:b2Body;
		protected var m_uiTag:uint = 0;
		protected var m_sprite:Sprite = null;
		protected var m_bIsAlive:Boolean = true;
		
		private var m_nOriginalX:Number = 0;
		private var m_nOriginalY:Number = 0;
		private var m_nOriginalWidth:Number = 0;
		private var m_nOriginalHeight:Number = 0;
		private var m_nOriginalRotation:Number = 0;
		
		/* public functions */
		/**
		 * Creates a new game object.
		 */
		public function GameObject(body:b2Body = null, uiTag:uint = 0, bIsAlive:Boolean = true, sprite:Sprite = null):void
		{
			m_b2Body = body;
			m_uiTag = uiTag;
			m_bIsAlive = bIsAlive;
			m_sprite = sprite;
		}
		
		/**
		 * Updates the sprite to the body's position. Takes in a boolean to check if user wants rotation updated too.
		 */
		public function updateSpriteToBody(bUpdateRotation:Boolean):void
		{
			if (m_sprite && m_b2Body)
			{
				m_sprite.x = m_b2Body.GetPosition().x * CommonMath.uiMETER_TO_PIXEL_RATIO;
				m_sprite.y = m_b2Body.GetPosition().y * CommonMath.uiMETER_TO_PIXEL_RATIO;
				
				if (bUpdateRotation)
				{
					m_sprite.rotation = body.GetAngle() * CommonMath.nTO_DEG;
				}
			}
		}
		
		/**
		 * Updates the body to the sprite's position. Takes in a boolean to check if user wants rotation updated too.
		 */
		public function updateBodyToSprite(bUpdateRotation:Boolean):void
		{
			if (m_sprite && m_b2Body)
			{
				m_b2Body.GetPosition().x = m_sprite.x / CommonMath.uiMETER_TO_PIXEL_RATIO;
				m_b2Body.GetPosition().y = m_sprite.y / CommonMath.uiMETER_TO_PIXEL_RATIO;
				
				if (bUpdateRotation)
				{
					body.SetAngle(CommonMath.degreeToRadian(sprite.rotation));
				}
			}
		}
		
		/**
		 * Resets all sprite's values to its respective original ones. Takes in a boolean to check if user wants to reset the sprite's size too.
		 */
		public function resetValues(bResetSize:Boolean):void
		{
			if (m_sprite)
			{
				m_sprite.x = m_nOriginalX;
				m_sprite.y = m_nOriginalY;
				m_sprite.rotation = m_nOriginalRotation;
				
				if (bResetSize)
				{
					m_sprite.width = m_nOriginalWidth;
					m_sprite.height = m_nOriginalHeight;
				}
			}
		}
		
		//properties
		/**
		 * Read-Only. The original x of a game object's sprite.
		 */
		public function get originalX():Number
		{
			return m_nOriginalX;
		}
		
		/**
		 * Read-Only. The original y of a game object's sprite.
		 */
		public function get originalY():Number
		{
			return m_nOriginalY;
		}
		
		/**
		 * Read-Only. The original width of a game object's sprite.
		 */
		public function get originalWidth():Number
		{
			return m_nOriginalWidth;
		}
		
		/**
		 * Read-Only. The original height of a game object's sprite.
		 */
		public function get originalHeight():Number
		{
			return m_nOriginalHeight;
		}
		
		/**
		 * Read-Only. The original rotation of a game object's sprite.
		 */
		public function get originalRotation():Number
		{
			return m_nOriginalRotation;
		}
		
		/**
		 * The tag of a game object.
		 */
		public function get tag():uint
		{
			return m_uiTag;
		}
		public function set tag(uiTag:uint):void
		{
			m_uiTag = uiTag;
		}
		
		/**
		 * The sprite of a game object
		 */
		public function get sprite():Sprite
		{
			return m_sprite;
		}
		public function set sprite(sprite:Sprite):void
		{
			if (sprite)
			{
				m_sprite = sprite;
			}
		}
		
		/**
		 * The b2Body of a game object
		 */
		public function get body():b2Body
		{
			return m_b2Body;
		}
		public function set body(body:b2Body):void
		{
			m_b2Body = body;
		}
		
		/**
		 * Determines whether or not the game objects should be destroyed.
		 */
		public function get isAlive():Boolean
		{
			return m_bIsAlive;
		}
		public function set isAlive(bIsAlive:Boolean):void
		{
			m_bIsAlive = bIsAlive;
		}
		
		/* protected functions */
		/**
		 * Sets all orginal values of the sprite for later reference
		 */
		protected function setOriginalValues(nOrigX:Number, nOrigY:Number, nOrigWidth:Number, nOrigHeight:Number, nOrigRot:Number):void
		{
			m_nOriginalX = nOrigX;
			m_nOriginalY = nOrigY;
			m_nOriginalWidth = nOrigWidth;
			m_nOriginalHeight = nOrigHeight;
			m_nOriginalRotation = nOrigRot;
		}
	}

}
